<template>
  <div class="chat-box" @click="closeRefBox()" @mousemove="readedMessage()">
    <!-- <div class="rtc-video-mine">
            <video ref="cam" width="128" height="96" autoplay controls></video>
        </div> -->
    <el-dialog v-dialogDrag top="5vh" custom-class="rtc-private-video-dialog" :title="null" :width="'600'" ref="xx"
               eager :visible.sync="showCameraUtil" :close-on-click-modal="false" :close-on-press-escape="false"
               :before-close="closeCamera">
      <div>
        <video v-show="!showPhoto" ref="cam" width="300" height="300" muted autoPlay playsInline
               controls></video>
        <canvas v-show="showPhoto" ref="photo" width="300" height="300"></canvas>
        <div>
          <el-button type="primary" icon="el-icon-s-promotion" @click="takePhoto()">Filming</el-button>
          <el-button type="primary" icon="el-icon-s-promotion" @click="selectPhoto()">Confirm</el-button>
          <el-button type="primary" icon="el-icon-s-promotion" @click="cancelPhoto()">Cancel</el-button>
          <el-button type="primary" icon="el-icon-s-promotion" @click="startRecording()">Start Record</el-button>
          <el-button type="primary" icon="el-icon-s-promotion" @click="stopRecording()">Finish Record</el-button>
          <el-button type="primary" icon="el-icon-s-promotion" @click="restartRecording()">Re-video</el-button>
          <el-button type="primary" icon="el-icon-s-promotion" @click="selectVideo()">Select Video</el-button>
        </div>

      </div>
    </el-dialog>
    <el-container>
      <el-header height="50px">
        <span>{{ title }}</span>
        <span title="Group message" v-show="this.chat.type == 'GROUP'" class="btn-side el-icon-more"
              @click="showSide = !showSide"></span>
      </el-header>
      <el-main style="padding: 0;">
        <el-container>
          <el-container class="content-box">
            <el-main class="im-chat-main" id="chatScrollBox" @scroll="onScroll">
              <div class="im-chat-box">
                <ul>
                  <li v-for="(msgInfo, idx) in chat.messages" :key="idx">
                    <chat-message-item v-if="idx >= showMinIdx" @call="onCall(msgInfo.type)"
                                       :mine="msgInfo.sendId == mine.id" :headImage="headImage(msgInfo)"
                                       :showName="showName(msgInfo)" :msgInfo="msgInfo"
                                       :groupMembers="groupMembers" @delete="deleteMessage"
                                       @recall="recallMessage">
                    </chat-message-item>
                  </li>
                </ul>
              </div>
            </el-main>
            <el-footer height="220px" class="im-chat-footer">
              <div class="chat-tool-bar">
                <div title="Camera" class="icon iconfont icon-camera-on" ref="camera"
                     @click.stop="openCamera()">
                </div>

                <div title="Emotion" class="icon iconfont icon-emoji" ref="emotion"
                     @click.stop="showEmotionBox()">
                </div>
                <div title="Image">
                  <file-upload :action="'/image/upload'" :maxSize="5 * 1024 * 1024"
                               :fileTypes="['image/jpeg', 'image/png', 'image/jpg', 'image/webp', 'image/gif']"
                               @before="onImageBefore" @success="onImageSuccess" @fail="onImageFail">
                    <i class="el-icon-picture-outline"></i>
                  </file-upload>
                </div>
                <div title="File">
                  <file-upload ref="fileUpload" :action="'/file/upload'" :maxSize="10 * 1024 * 1024"
                               @before="onFileBefore" @success="onFileSuccess" @fail="onFileFail">
                    <i class="el-icon-wallet"></i>
                  </file-upload>
                </div>
                <div title="Receipt Message" v-show="chat.type == 'GROUP'" class="icon iconfont icon-receipt"
                     :class="isReceipt ? 'chat-tool-active' : ''" @click="onSwitchReceipt">
                </div>
                <div title="Send Voice" class="el-icon-microphone" @click="showRecordBox()">
                </div>
                <div title="Voice Call" v-show="chat.type == 'PRIVATE'" class="el-icon-phone-outline"
                     @click="showPrivateVideo('voice')">
                </div>
                <div title="Voice Call" v-show="chat.type == 'GROUP'" class="el-icon-phone-outline"
                     @click="onGroupVideo()">
                </div>
                <div title="Video Call" v-show="chat.type == 'PRIVATE'" class="el-icon-video-camera"
                     @click="showPrivateVideo('video')">
                </div>
                <div title="Chat History" class="el-icon-chat-dot-round" @click="showHistoryBox()"></div>
              </div>
              <div class="send-content-area">
                <ChatInput :ownerId="group.ownerId" ref="chatInputEditor" :group-members="groupMembers"
                           @submit="sendMessage" />
                <div class="send-btn-area">
                  <el-button type="primary" icon="el-icon-s-promotion"
                             @click="notifySend()">Send</el-button>
                </div>
              </div>
            </el-footer>
          </el-container>
          <el-aside class="chat-group-side-box" width="260px" v-if="showSide">
            <chat-group-side :group="group" :groupMembers="groupMembers" @reload="loadGroup(group.id)">
            </chat-group-side>
          </el-aside>
        </el-container>
      </el-main>
      <emotion ref="emoBox" @emotion="onEmotion"></Emotion>
      <chat-record :visible="showRecord" @close="closeRecordBox" @send="onSendRecord"></chat-record>
      <group-member-selector ref="rtcSel" :groupId="group.id" @complete="onInviteOk"></group-member-selector>
      <rtc-group-join ref="rtcJoin" :groupId="group.id"></rtc-group-join>
      <chat-history :visible="showHistory" :chat="chat" :friend="friend" :group="group"
                    :groupMembers="groupMembers" @close="closeHistoryBox"></chat-history>
    </el-container>
  </div>
</template>

<script>
import ChatGroupSide from "./ChatGroupSide.vue";
import ChatMessageItem from "./ChatMessageItem.vue";
import FileUpload from "../common/FileUpload.vue";
import Emotion from "../common/Emotion.vue";
import ChatRecord from "./ChatRecord.vue";
import ChatHistory from "./ChatHistory.vue";
import ChatAtBox from "./ChatAtBox.vue"
import GroupMemberSelector from "../group/GroupMemberSelector.vue"
import RtcGroupJoin from "../rtc/RtcGroupJoin.vue"
import ChatInput from "./ChatInput";
// import { CryptoUtil } from "../../api/cryptoUtil";
import { CameraUtil } from "./cameraUtil.js";
import ImCamera from '@/api/camera';
import {Dialog} from "vant";
import {CryptoUtil} from "@/api/cryptoUtil";


export default {
  name: "chatPrivate",
  components: {
    ChatInput,
    ChatMessageItem,
    FileUpload,
    ChatGroupSide,
    Emotion,
    ChatRecord,
    ChatHistory,
    ChatAtBox,
    GroupMemberSelector,
    RtcGroupJoin
  },
  props: {
    chat: {
      type: Object
    }
  },
  data() {
    return {
      friend: {},
      group: {},
      groupMembers: [],
      sendImageUrl: "",
      sendImageFile: "",
      placeholder: "",
      isReceipt: true,
      showRecord: false,
      showSide: false,
      showHistory: false,
      lockMessage: false,
      showMinIdx: 0,
      reqQueue: [],
      cameraUtil: new CameraUtil(),
      camera: new ImCamera(),

      showCameraUtil: false,
      showPhoto: false,

      cryptoObj: {
        cryptoUtil: undefined,
        keyObj: undefined,
        sendCke: undefined,
      },

      recordedBlobs: [],
      mediaRecorder: undefined,
      localStream: undefined,

      isSending: false
    }
  },
  methods: {
    moveChatToTop() {
      let chatIdx = this.$store.getters.findChatIdx(this.chat);
      this.$store.commit("moveTop", chatIdx);
    },
    closeRefBox() {
      this.$refs.emoBox.close();
      // this.$refs.atBox.close();
    },
    onCall(type) {
      if (type == this.$enums.MESSAGE_TYPE.ACT_RT_VOICE) {
        this.showPrivateVideo('voice');
      } else if (type == this.$enums.MESSAGE_TYPE.ACT_RT_VIDEO) {
        this.showPrivateVideo('video');
      }
    },
    onSwitchReceipt() {
      this.isReceipt = !this.isReceipt;
      this.refreshPlaceHolder();
    },
    onImageSuccess(data, file) {
      let msgInfo = JSON.parse(JSON.stringify(file.msgInfo));
      msgInfo.content = JSON.stringify(data);
      msgInfo.receipt = this.isReceipt;
      this.sendMessageRequest(msgInfo).then((m) => {
        msgInfo.loadStatus = 'ok';
        msgInfo.id = m.id;
        this.isReceipt = false;
        this.$store.commit("insertMessage", msgInfo);
      })
    },
    onImageFail(e, file) {
      let msgInfo = JSON.parse(JSON.stringify(file.msgInfo));
      msgInfo.loadStatus = 'fail';
      this.$store.commit("insertMessage", msgInfo);
    },
    onImageBefore(file) {
      let url = URL.createObjectURL(file);
      let data = {
        originUrl: url,
        thumbUrl: url
      }
      let msgInfo = {
        id: 0,
        tmpId: this.generateId(),
        fileId: file.uid,
        sendId: this.mine.id,
        content: JSON.stringify(data),
        sendTime: new Date().getTime(),
        selfSend: true,
        type: 1,
        readedCount: 0,
        loadStatus: "loading",
        status: this.$enums.MESSAGE_STATUS.UNSEND
      }
      this.fillTargetId(msgInfo, this.chat.targetId);
      this.$store.commit("insertMessage", msgInfo);
      this.moveChatToTop();
      this.scrollToBottom();
      file.msgInfo = msgInfo;
    },
    onFileSuccess(url, file) {
      let data = {
        name: file.name,
        size: file.size,
        url: url
      }
      let msgInfo = JSON.parse(JSON.stringify(file.msgInfo));
      msgInfo.content = JSON.stringify(data);
      msgInfo.receipt = this.isReceipt
      this.sendMessageRequest(msgInfo).then((m) => {
        msgInfo.loadStatus = 'ok';
        msgInfo.id = m.id;
        this.isReceipt = false;
        this.refreshPlaceHolder();
        this.$store.commit("insertMessage", msgInfo);
      })
    },
    onFileFail(e, file) {
      let msgInfo = JSON.parse(JSON.stringify(file.msgInfo));
      msgInfo.loadStatus = 'fail';
      this.$store.commit("insertMessage", msgInfo);
    },
    onFileBefore(file) {
      let url = URL.createObjectURL(file);
      let data = {
        name: file.name,
        size: file.size,
        url: url
      }
      let msgInfo = {
        id: 0,
        tmpId: this.generateId(),
        sendId: this.mine.id,
        content: JSON.stringify(data),
        sendTime: new Date().getTime(),
        selfSend: true,
        type: 2,
        loadStatus: "loading",
        readedCount: 0,
        status: this.$enums.MESSAGE_STATUS.UNSEND
      }
      this.fillTargetId(msgInfo, this.chat.targetId);
      this.$store.commit("insertMessage", msgInfo);
      this.moveChatToTop();
      this.scrollToBottom();
      file.msgInfo = msgInfo;
    },
    onCloseSide() {
      this.showSide = false;
    },
    onScrollToTop() {
      this.showMinIdx = this.showMinIdx > 10 ? this.showMinIdx - 10 : 0;
    },
    onScroll(e) {
      let scrollElement = e.target
      let scrollTop = scrollElement.scrollTop
      if (scrollTop < 30) {
        this.showMinIdx = this.showMinIdx > 20 ? this.showMinIdx - 20 : 0;
      }
    },
    openCamera() {
      /*this.cameraUtil.open()
        .then(stream => {
          this.showCameraUtil = true;
          this.$nextTick(() => {
            this.$refs.cam.srcObject = stream;
            this.$refs.cam.play();
            // console.log('video', video, stream);
          })
          // alert('stream')
          // alert(stream)
          // this.$refs.cameraStream.srcObject = stream
          // console.log(this.$refs.xx);
          // console.log(this.$refs.cam);
          // console.log(this.$refs.remoteVideo);
          // const video = document.getElementById('remoteVideo');
          // console.log('video', video);
          // video.srcObject = stream


        })
        .catch(err => {
          alert('err')
          alert(err)
        });*/

      this.camera.openVideo().then((stream) => {
        // this.localStream = stream;
        this.localStream = stream;
        this.showCameraUtil = true;
        this.$nextTick(() => {
          this.$refs.cam.srcObject = stream;
          this.$refs.cam.muted = true;
          //   this.$refs.cam.play();
        })
        // resolve(stream);
      }).catch((e) => {
        this.$message.error("Failed to open the camera")
        console.log("Failed to open the camera:" + e.message)
        // reject(e);
      })
    },
    closeCamera() {
      this.camera.close();
      this.showCameraUtil = false;
    },
    takePhoto() {
      this.$refs.photo.getContext("2d").drawImage(this.$refs.cam, 0, 0, 300, 300);
      this.showPhoto = true;
    },
    selectPhoto() {
      this.$refs.photo.toBlob((blob) => {
        console.log(blob);
        this.$refs.chatInputEditor.insertImage(blob);
      });
      this.closeCamera();


      // this.$refs.chatInputEditor.insertEmoji(emoText);
    },
    selectVideo() {
      const blob = new Blob(this.recordedBlobs, { type: 'video/webm' });
      const element = this.$refs.chatInputEditor.insertVideo(blob);
      this.displayV(blob, element);
      console.log('displayV', blob);
      this.closeCamera();

      // this.$refs.chatInputEditor.insertEmoji(emoText);
    },
    cancelPhoto() {
      this.$refs.photo.getContext("2d").drawImage(this.$refs.cam, 0, 0, 300, 300);
      this.showPhoto = true;
    },
    startRecording() {
      this.recordedBlobs = [];

      this.mediaRecorder = new MediaRecorder(this.localStream, { mimeType: 'video/webm' });
      this.mediaRecorder.ondataavailable = (event) => {
        console.log('ondataavailable', event);
        if (event.data && event.data.size > 0) {
          this.recordedBlobs.push(event.data);
        }
      };
      this.mediaRecorder.start(100);
      console.log('Recording started', this.localStream);
    },
    stopRecording() {

      console.log('Recording stop');
      this.mediaRecorder.stop();
      this.$refs.cam.srcObject = null;
      // this.$refs.cam.stop();
      const blob = new Blob(this.recordedBlobs, { type: 'video/webm' });
      console.log('stopRecording', this.recordedBlobs, blob);

      const url = URL.createObjectURL(blob);
      // this.$refs.cam.src = url;
      this.displayV(blob, this.$refs.cam);
    },
    restartRecording() {
      this.$refs.cam.srcObject = this.localStream;
    },
    displayV(videoFile, videoEl) {

      // Preconditions:
      if (!(videoFile instanceof Blob)) throw new Error('`videoFile` must be a Blob or File object.'); // The `File` prototype extends the `Blob` prototype, so `instanceof Blob` works for both.
      if (!(videoEl instanceof HTMLVideoElement)) throw new Error('`videoEl` must be a <video> element.');

      //

      const newObjectUrl = URL.createObjectURL(videoFile);

      // URLs created by `URL.createObjectURL` always use the `blob:` URI scheme: https://w3c.github.io/FileAPI/#dfn-createObjectURL
      const oldObjectUrl = videoEl.currentSrc;
      if (oldObjectUrl && oldObjectUrl.startsWith('blob:')) {
        // It is very important to revoke the previous ObjectURL to prevent memory leaks. Un-set the `src` first.
        // See https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL

        videoEl.src = ''; // <-- Un-set the src property *before* revoking the object URL.
        URL.revokeObjectURL(oldObjectUrl);
      }

      // Then set the new URL:
      videoEl.src = newObjectUrl;

      // And load it:
      videoEl.load(); // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/load

    },

    showEmotionBox() {
      let width = this.$refs.emotion.offsetWidth;
      let left = this.$elm.fixLeft(this.$refs.emotion);
      let top = this.$elm.fixTop(this.$refs.emotion);
      this.$refs.emoBox.open({
        x: left + width / 2,
        y: top
      })
    },
    onEmotion(emoText) {
      this.$refs.chatInputEditor.insertEmoji(emoText);
    },
    showRecordBox() {
      this.showRecord = true;
    },
    closeRecordBox() {
      this.showRecord = false;
    },
    showPrivateVideo(mode) {
      let rtcInfo = {
        mode: mode,
        isHost: true,
        friend: this.friend,
      }
      // Open a single-player video window through home.vue
      this.$eventBus.$emit("openPrivateVideo", rtcInfo);
    },
    onGroupVideo() {
      // Invite members to start a call
      let ids = [this.mine.id];
      let maxChannel = this.$store.state.configStore.webrtc.maxChannel;
      this.$refs.rtcSel.open(maxChannel, ids, ids);
    },
    onInviteOk(members) {
      if (members.length < 2) {
        return;
      }
      let userInfos = [];
      members.forEach(m => {
        userInfos.push({
          id: m.userId,
          nickName: m.showNickName,
          headImage: m.headImage,
          isCamera: false,
          isMicroPhone: true
        })
      })
      let rtcInfo = {
        isHost: true,
        groupId: this.group.id,
        inviterId: this.mine.id,
        userInfos: userInfos
      }
      // Open the multi-person video window through home.vue
      this.$eventBus.$emit("openGroupVideo", rtcInfo);
    },
    showHistoryBox() {
      this.showHistory = true;
    },
    closeHistoryBox() {
      this.showHistory = false;
    },
    onSendRecord(data) {
      let msgInfo = {
        content: JSON.stringify(data),
        type: 3,
        receipt: this.isReceipt
      }
      this.fillTargetId(msgInfo, this.chat.targetId);
      this.sendMessageRequest(msgInfo).then((m) => {
        m.selfSend = true;
        this.$store.commit("insertMessage", m);
        // Sticky conversation
        this.moveChatToTop();
        this.$refs.chatInputEditor.focus();
        this.scrollToBottom();
        this.showRecord = false;
        this.isReceipt = false;
        this.refreshPlaceHolder();
      })
    },
    fillTargetId(msgInfo, targetId) {
      if (this.chat.type == "GROUP") {
        msgInfo.groupId = targetId;
      } else {
        msgInfo.recvId = targetId;
      }
    },
    notifySend() {
      this.$refs.chatInputEditor.submit();
    },
    // async sendMessage(fullList) {
    //   this.resetEditor();
    //   this.readedMessage();
    //   let sendText = this.isReceipt ? "【Receipt message】" : "";
    //   let promiseList = [];
    //   for (let i = 0; i < fullList.length; i++) {
    //     let msg = fullList[i];
    //     switch (msg.type) {
    //       case "text":
    //         var content = sendText + msg.content
    //         // content = AES.encode('12345678', content)
    //         var code = 0
    //         var keyObj = {
    //           code,
    //           key: '12345678'
    //         }
    //         content = new CryptoUtil(code).encode(keyObj, content);
    //
    //         await this.sendTextMessage(content, msg.atUserIds);
    //         break;
    //       case "image":
    //         code = 0
    //         keyObj = {
    //           code,
    //           key: '12345678'
    //         }
    //         var reader = new FileReader();
    //         reader.readAsArrayBuffer(msg.content.file);
    //         reader.onload = () => {
    //           console.log('reader', reader.result);
    //
    //           var f = new CryptoUtil(code).encryptFile(reader.result, keyObj.key)
    //
    //           console.log('e', f);
    //           /*reader.readAsArrayBuffer(msg.content.file);
    //           reader.onload = () => {
    //             var ff = new CryptoUtil(code).decryptFile(reader.result, keyObj.key));
    //             this.sendImageMessage(ff);
    //           }//*/
    //
    //           this.sendImageMessage(f);
    //         }
    //
    //         // content = new CryptoUtil(code).encode(keyObj, content);
    //
    //         // await this.sendImageMessage(msg.content.file);
    //         break;
    //       case "file":
    //         await this.sendFileMessage(msg.content.file);
    //         break;
    //     }
    //
    //   }
    // },
    sendImageMessage(file) {
      console.log('send img', file);

      return new Promise((resolve, reject) => {
        this.onImageBefore(file);
        let formData = new FormData()
        formData.append('file', file)
        this.$http.post("/image/upload", formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        }).then((data) => {
          this.onImageSuccess(data, file);
          resolve();
        }).catch((res) => {
          this.onImageFail(res, file);
          reject();
        })
        this.$nextTick(() => this.$refs.chatInputEditor.focus());
        this.scrollToBottom();
      });
    },
    sendTextMessage(sendText, atUserIds) {
      return new Promise((resolve, reject) => {
        if (!sendText.trim()) {
          reject();
        }
        let msgInfo = {
          content: sendText,
          type: 0
        }
        this.fillTargetId(msgInfo, this.chat.targetId);
        // List of people being @ed
        if (this.chat.type == "GROUP") {
          msgInfo.atUserIds = atUserIds;
          msgInfo.receipt = this.isReceipt;
        }
        this.lockMessage = true;
        this.sendMessageRequest(msgInfo).then((m) => {
          m.selfSend = true;
          this.$store.commit("insertMessage", m);
          this.moveChatToTop();
        }).finally(() => {
          // Unlock
          this.scrollToBottom();
          this.isReceipt = false;
          resolve();
        });
      });
    },
    sendFileMessage(file) {
      console.log('send file', file);
      return new Promise((resolve, reject) => {
        let check = this.$refs.fileUpload.beforeUpload(file);
        if (check) {
          this.$refs.fileUpload.onFileUpload({ file });
        }
      })
    },
    deleteMessage(msgInfo) {
      Dialog.confirm({
        title: 'Delete message',
        message: `Confirm delete the message?`,
        confirmButtonColor: 'var(--chat-theme-color)',
        confirmButtonText: 'Confirm',
        cancelButtonText: 'Cancel',
      }).then(() => {
        this.$store.commit("deleteMessage", msgInfo);
      });
    },
    recallMessage(msgInfo) {
      Dialog.confirm({
        title: 'Recall message',
        message: `Confirm recall the message?`,
        confirmButtonColor: 'var(--chat-theme-color)',
        confirmButtonText: 'Confirm',
        cancelButtonText: 'Cancel',
      }).then(() => {
        let url = `/message/${this.chat.type.toLowerCase()}/recall/${msgInfo.id}`
        this.$http({
          url: url,
          method: 'delete'
        }).then(() => {
          this.$message.success("the message is recalled");
          msgInfo = JSON.parse(JSON.stringify(msgInfo));
          msgInfo.type = 10;
          msgInfo.content = 'You retracted a message';
          msgInfo.status = this.$enums.MESSAGE_STATUS.RECALL;
          this.$store.commit("insertMessage", msgInfo);
        })
      });
    },
    readedMessage() {
      if (this.chat.unreadCount == 0) {
        return;
      }
      this.$store.commit("resetUnreadCount", this.chat)
      if (this.chat.type == "GROUP") {
        var url = `/message/group/readed?groupId=${this.chat.targetId}`
      } else {
        url = `/message/private/readed?friendId=${this.chat.targetId}`
      }
      this.$http({
        url: url,
        method: 'put'
      }).then(() => { })
    },
    loadReaded(fId) {
      this.$http({
        url: `/message/private/maxReadedId?friendId=${fId}`,
        method: 'get'
      }).then((id) => {
        this.$store.commit("readedMessage", {
          friendId: fId,
          maxId: id
        });
      });
    },
    loadGroup(groupId) {
      this.$http({
        url: `/group/find/${groupId}`,
        method: 'get'
      }).then((group) => {
        this.group = group;
        this.$store.commit("updateChatFromGroup", group);
        this.$store.commit("updateGroup", group);
      });

      this.$http({
        url: `/group/members/${groupId}`,
        method: 'get'
      }).then((groupMembers) => {
        this.groupMembers = groupMembers;
      });
    },
    loadFriend(friendId) {
      this.$http({
        url: `/user/find/${friendId}`,
        method: 'get'
      }).then((friend) => {
        this.friend = friend;
        this.$store.commit("updateChatFromFriend", friend);
        this.$store.commit("updateFriend", friend);
      })
    },
    showName(msgInfo) {
      // console.log('showName', msgInfo);
      if (this.chat.type == 'GROUP') {
        let member = this.groupMembers.find((m) => m.userId == msgInfo.sendId);
        return member ? member.showNickName : "";
      } else {
        return msgInfo.sendId == this.mine.id ? this.mine.nickName : this.chat.showName
      }

    },
    headImage(msgInfo) {
      if (this.chat.type == 'GROUP') {
        let member = this.groupMembers.find((m) => m.userId == msgInfo.sendId);
        return member ? member.headImage : "";
      } else {
        return msgInfo.sendId == this.mine.id ? this.mine.headImageThumb : this.chat.headImage
      }
    },
    resetEditor() {

      this.$nextTick(() => {
        this.$refs.chatInputEditor.clear();
        this.$refs.chatInputEditor.focus();
      });
    },
    scrollToBottom() {
      this.$nextTick(() => {
        let div = document.getElementById("chatScrollBox");
        div.scrollTop = div.scrollHeight;
      });
    },
    refreshPlaceHolder() {
      if (this.isReceipt) {
        this.placeholder = "【Receipt message】"
      } else if (this.$refs.editBox && this.$refs.editBox.innerHTML) {
        this.placeholder = ""
      } else {
        this.placeholder = "Let's talk about something~";
      }
    },
    sendMessageRequest(msgInfo) {

      var cryptoUtil = this.cryptoObj.cryptoUtil
      var keyObj = this.cryptoObj.keyObj
      var sendCke = this.cryptoObj.sendCke
      msgInfo.sendCke = sendCke

      var msgInfoCopy = JSON.parse(JSON.stringify(msgInfo))
      msgInfoCopy.content = cryptoUtil.encode(keyObj, msgInfoCopy.content);
      console.log('sendMessageRequest', this.cryptoObj, msgInfoCopy)



      return new Promise((resolve, reject) => {
        // Requests are queued to prevent "last-come-first-served" requests from causing message misordering
        this.reqQueue.push({ msgInfo: msgInfoCopy, resolve, reject });
        this.processReqQueue();
      })
    },
    processReqQueue() {
      if (this.reqQueue.length && !this.isSending) {
        this.isSending = true;
        const reqData = this.reqQueue.shift();
        this.$http({
          url: this.messageAction,
          method: 'post',
          data: reqData.msgInfo
        }).then((res) => {
          reqData.resolve(res)
        }).catch((e) => {
          reqData.reject(e)
        }).finally(() => {
          this.isSending = false;
          // send next request
          this.processReqQueue();
        })
      }
    },
    generateId() {
      // tmp id
      return String(new Date().getTime()) + String(Math.floor(Math.random() * 1000));
    }
  },
  computed: {
    mine() {
      return this.$store.state.userStore.userInfo;
    },
    title() {
      let title = this.chat.showName;
      if (this.chat.type == "GROUP") {
        let size = this.groupMembers.filter(m => !m.quit).length;
        title += `(${size})`;
      }
      return title;
    },
    messageAction() {
      return `/message/${this.chat.type.toLowerCase()}/send`;
    },
    unreadCount() {
      return this.chat.unreadCount;
    },
    messageSize() {
      if (!this.chat || !this.chat.messages) {
        return 0;
      }
      return this.chat.messages.length;
    },
    xx() {
      return this.$refs['xx']
    }
  },
  watch: {
    chat: {
      handler(newChat, oldChat) {
        if (newChat.targetId > 0 && (!oldChat || newChat.type != oldChat.type ||
            newChat.targetId != oldChat.targetId)) {
          if (this.chat.type == "GROUP") {
            this.loadGroup(this.chat.targetId);
          } else {
            this.loadFriend(this.chat.targetId);
            this.loadReaded(this.chat.targetId)
          }
          this.scrollToBottom();
          this.showSide = false;
          // readed
          this.readedMessage()
          // Initially only 30 messages are displayed
          let size = this.chat.messages.length;
          this.showMinIdx = size > 30 ? size - 30 : 0;
          this.resetEditor();
          this.isReceipt = false;
          this.refreshPlaceHolder();
        }
      },
      immediate: true
    },
    messageSize: {
      handler(newSize, oldSize) {
        if (newSize > oldSize) {
          this.scrollToBottom();
        }
      }
    }
  },
  mounted() {
    let div = document.getElementById("chatScrollBox");
    div.addEventListener('scroll', this.onScroll);
    /*this.cameraUtil.open()
        .then(stream => {
          console.log('stream', stream);
          this.$refs.cam.srcObject = stream;
            this.$refs.cam.play();
        })
        .catch(err => {
          console.log('err', err);
        })*/

    // window.onbeforeunload = () => {
    // 	console.log('onbeforeunload');
    //   // videoRef.current.srcObject = null
    //   const tracks = this.$refs.cam.srcObject.getTracks();
    //   this.$refs.cam.srcObject = null;
    //   console.log(tracks);
    //   tracks.forEach(function(track) {
    //     track.stop();
    // 	console.log(track);
    //   });
    //   console.log('after onbeforeunload');
    // }

    // // open camera+microPhone
    // this.camera.openVideo().then((stream) => {
    // 	// this.localStream = stream;
    // 	this.$nextTick(() => {
    // 		this.$refs.cam.srcObject = stream;
    // 		this.$refs.cam.muted = true;
    // 		this.$refs.cam.play();
    // 	})
    // 	// resolve(stream);
    // }).catch((e) => {
    // 	this.$message.error("The camera failed to open")
    // 	console.log("The camera failed to open:" + e.message)
    // 	// reject(e);
    // })

    var code = Number(sessionStorage.getItem("code"));
    var cryptoUtil = new CryptoUtil(code);
    var keyObj = cryptoUtil.randomKeyObj(null);
    // var keyObj = cryptoUtil.randomKeyObj(sessionStorage.getItem("psha256"));
    var keyForKeyObj = cryptoUtil.randomKeyObj(sessionStorage.getItem("psha256"))
    var sendCke = cryptoUtil.encode(keyForKeyObj, JSON.stringify(keyObj));

    this.cryptoObj = {
      cryptoUtil: cryptoUtil,
      keyObj: keyObj,
      sendCke: sendCke,
    }
  }
}
</script>

<style lang="scss">
.chat-box {
  position: relative;
  width: 100%;
  background: #fff;

  .el-header {
    display: flex;
    justify-content: space-between;
    padding: 0 12px;
    line-height: 50px;
    font-size: var(--im-font-size-larger);
    border-bottom: var(--im-border);


    .btn-side {
      position: absolute;
      right: 20px;
      line-height: 50px;
      font-size: 20px;
      cursor: pointer;
      color: var(--im-text-color-light);
    }
  }

  .im-chat-main {
    padding: 0;
    background-color: #fff;

    .im-chat-box {
      >ul {
        padding: 0 20px;
        // 				li:before{
        //     display:inline-block; width:10px; height:10px;
        //     line-height:10px; content:""; border:1px #000 solid;
        //     margin-right:2px; transition:all 0.3s linear;
        // }

        li {
          list-style-type: none;
        }
      }
    }
  }

  .im-chat-footer {
    display: flex;
    flex-direction: column;
    padding: 0;

    .chat-tool-bar {
      display: flex;
      position: relative;
      width: 100%;
      height: 36px;
      text-align: left;
      box-sizing: border-box;
      border-top: var(--im-border);
      padding: 4px 2px 2px 8px;

      >div {
        font-size: 22px;
        cursor: pointer;
        line-height: 30px;
        width: 30px;
        height: 30px;
        text-align: center;
        border-radius: 2px;
        margin-right: 8px;
        color: #999;
        transition: 0.3s;

        &.chat-tool-active {
          font-weight: 600;
          color: var(--im-color-primary);
          background-color: #ddd;
        }
      }

      >div:hover {
        color: #333;
      }
    }

    .send-content-area {
      position: relative;
      display: flex;
      flex-direction: column;
      height: 100%;
      background-color: white !important;

      .send-text-area {
        box-sizing: border-box;
        padding: 5px;
        width: 100%;
        flex: 1;
        resize: none;
        font-size: 16px;
        outline: none;

        text-align: left;
        line-height: 30px;

        &:before {
          content: attr(placeholder);
          color: gray;
        }

        .at {
          color: blue;
          font-weight: 600;
        }

        .receipt {
          color: darkblue;
          font-size: 15px;
          font-weight: 600;
        }

        .emo {
          width: 30px;
          height: 30px;
          vertical-align: bottom;
        }
      }

      .send-image-area {
        text-align: left;
        border: #53a0e7 solid 1px;

        .send-image-box {
          position: relative;
          display: inline-block;

          .send-image {
            max-height: 180px;
            border: 1px solid #ccc;
            border-radius: 2%;
            margin: 2px;
          }

          .send-image-close {
            position: absolute;
            padding: 3px;
            right: 7px;
            top: 7px;
            color: white;
            cursor: pointer;
            font-size: 15px;
            font-weight: 600;
            background-color: #aaa;
            border-radius: 50%;
            border: 1px solid #ccc;
          }
        }
      }

      .send-btn-area {
        padding: 10px;
        position: absolute;
        bottom: 4px;
        right: 6px;
      }
    }
  }

  .chat-group-side-box {
    border-left: var(--im-border);
    //animation: rtl-drawer-in .3s 1ms;
  }

}
</style>
